There are a few obscure pitfalls in X client code. One area is dealing with X window properties. X window properties are named and typed arrays of data that can be associated with a window. Properties are useful for inter-client communication, particularly with the window manager.
Properties come in 8-bit, 16-bit, and 32-bit data formats. Be careful when setting or querying a property with 32-bit data. When specifying a 32-bit property data format using XChangeProperty or XGetWindowProperty, the property data is laid out in an array of long values. This is not obvious from the prototypes of these routines that deceptively claim the data is passed to the routine as an unsigned char*. In truth, 32-bit property data is specified to be laid out in an array of long sized data. While in the 32-bit world, an array of longs would mean the 32-bit values were arranged in a contiguous list, in the 64-bit LP64 model, the array will be of 64-bit long values, each logically holding a 32-bit value.
The following code would not be portable to a 64-bit LP64 machine:
/* overlayInfo should be pointer to long, not int! */ int *overlayInfo; Atom overlayVisualsAtom, actualType; unsigned long sizeData, bytesLeft; int actualFormat; overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True); status = XGetWindowProperty(dpy, root, overlayVisualsAtom, 0L, 10000L, False, overlayVisualsAtom, &actualType, &actualFormat, &sizeData, &bytesLeft, (unsigned char**) &overlayInfo); if(status != Success || actualType != overlayVisualsAtom || actualFormat != 32 || sizeData < 4) { /* bogus property */ } else { /* process info returned in array overlayInfo */ }
While the code compiles
correctly, the subtle problem is that the
overlayInfo variable (first line) is declared to be an array of int
data, instead of long data as Xlib expects it to be if the
property is to contain 32-bit data. On a 64-bit LP64 machine, the overlayInfo
contains scattered pieces of the actual data for the property. Because
the cast of overlayInfo to (unsigned char**) is necessary
to match the prototype of XGetWindowProperty, this kind of subtle
typing problem cannot be caught by compilers.
Code using 8-byte or 16-byte property data is likely to work without modification because the char and short data types do not change size.